package cn.ddiancan.xddcloud.ddccore.filter;

import cn.ddiancan.xddcloud.common.constants.XddHeaderConstant;
import cn.ddiancan.xddcloud.common.context.RequestContext;
import cn.ddiancan.xddcloud.common.context.RequestContextManager;
import cn.ddiancan.xddcloud.common.entity.UserVO;
import cn.ddiancan.xddcloud.common.security.JwtService;
import cn.ddiancan.xddcloud.ddccore.cache.XddCloudCacheClient;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Objects;

/**
 * 上下文拦截器，下沉用户信息
 *
 * @author Amos
 */
public class ContextFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(ContextFilter.class);

    private final XddCloudCacheClient xddCloudCacheClient;

    private final JwtService jwtService;

    public ContextFilter(XddCloudCacheClient xddCloudCacheClient, JwtService jwtService) {
        this.xddCloudCacheClient = xddCloudCacheClient;
        this.jwtService = jwtService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        String authToken = request.getHeader(XddHeaderConstant.X_AUTH_TOKEN);
        logger.info("-----------------x-auth-token:{}", authToken);
        if (!StringUtils.hasText(authToken)) {
            filterChain.doFilter(request, response);
            return;
        }
        try {
            String jwtToken = request.getHeader(XddHeaderConstant.X_JWT_TOKEN);
            // 解析jwttoken
            UserVO userInfo = jwtService.getUserInfo(jwtToken);
            if (Objects.isNull(userInfo)) {
                userInfo = xddCloudCacheClient.get(authToken);
            }
            // redis作为兜底，理论上，用jwt进行用户签名在微服务间传递更合适，后续完善
            RequestContext<UserVO> requestContext = new RequestContext<>(userInfo);
            RequestContextManager.constructRequestContext(requestContext);
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            RequestContextManager.releaseRequestContext();
        }
    }
}
